#include "StdAfx.h"
#include "packet_impl.h"
#include <ace/message_block.h>
#include <interface/aot_inet_cdr.h>

packet_impl::packet_impl(void)
{
	token_ = NULL;
	body_ = NULL;
	header_ = NULL;
}

packet_impl::~packet_impl(void)
{
	if( body_ )
	{
		body_->release();
		body_ = NULL;
	}

	if( header_ )
	{
		header_->release();
		header_ = NULL;
	}
}

bool 
packet_impl::query_interface (void** out, const char* key)
{
	return false;
}

char*  
packet_impl::body_base()
{
	return this->body_->base();
}

size_t 
packet_impl::body_space()
{
	return this->body_->space();
}

size_t 
packet_impl::body_length()
{
	return this->body_->length();
}

size_t   
packet_impl::body_size()
{
	return this->body_->size();
}

char*  
packet_impl::body_rd_ptr()
{
	return this->body_->rd_ptr();
}

void   
packet_impl::body_rd_ptr(size_t n)
{
	this->body_->rd_ptr(n);
}

void   
packet_impl::body_rd_ptr(char* p)
{
	this->body_->rd_ptr(p);
}

char*  
packet_impl::body_wr_ptr()
{
	return this->body_->wr_ptr();
}

void   
packet_impl::body_wr_ptr(size_t n)
{
	this->body_->wr_ptr(n);
}

void   
packet_impl::body_wr_ptr(char* p)
{
	this->body_->wr_ptr(p);
}

bool   
packet_impl::body_copy_from(const void* data, size_t len)
{
	if( 0 == this->body_->copy((const char*)data, len) )
	{
		return true;
	}
	return false;
}

bool   
packet_impl::create_body(size_t body_size)
{
	if( this->body_ )
	{
		this->body_->release();
		this->body_ = NULL;
	}
	ACE_NEW_RETURN(this->body_, ACE_Message_Block(body_size), false);
	return true;
}

void   
packet_impl::body_recycle()
{
	this->body_->reset();
}

void   
packet_impl::token(void* p)
{
	this->token_ = p;
}

void*  
packet_impl::token()
{
	return this->token_;
}

void*  
packet_impl::body_impl()
{
	return this->body_;
}

void   
packet_impl::body_impl(void* p)
{
	this->body_ = (ACE_Message_Block*)p;
}

bool   
packet_impl::create_header(size_t len)
{
	if( this->header_ )
	{
		this->header_->release();
		this->header_ = NULL;
	}
	ACE_NEW_RETURN(this->header_, ACE_Message_Block(len), false);
	return true;
}

void*  
packet_impl::header_impl()
{
	return this->header_;
}

void   
packet_impl::header_impl(void* p)
{
	this->header_ = (ACE_Message_Block*)p;
}

char*  
packet_impl::header_base()
{
	return this->header_->base();
}

char*  
packet_impl::header_rd_ptr()
{
	return this->header_->rd_ptr();
}

void   
packet_impl::header_rd_ptr(size_t n)
{
	this->header_->rd_ptr(n);
}

void   
packet_impl::header_rd_ptr(char* p)
{
	this->header_->rd_ptr(p);
}

char*  
packet_impl::header_wr_ptr()
{
	return this->header_->wr_ptr();
}

void   
packet_impl::header_wr_ptr(size_t n)
{
	this->header_->wr_ptr(n);
}

void   
packet_impl::header_wr_ptr(char* p)
{
	this->header_->wr_ptr(p);
}

void   
packet_impl::header_recycle()
{
	this->header_->reset();
}

bool   
packet_impl::build_header(aot_uint32_t body_len, aot_uint32_t extern_header_len, 
						  aot_uint16_t type, 
						  aot_uint8_t encrypt_type, 
						  aot_uint8_t vers)
{
	if( !create_header() )
		return false;

	aot::inet::packet_header h(this->header_->base());
	memset(this->header_->base(), 0, aot::inet::PKT_HEADER_LEN);

	h.version(vers);
	h.type(type);
	h.encrypt_type(encrypt_type);
	h.extern_header_len(extern_header_len);
	h.data_len(body_len);

	this->header_->wr_ptr(aot::inet::PKT_HEADER_LEN);

	return true;
}

aot::inet::ipacket* 
packet_impl::clone()
{
	packet_impl* p = packet_impl::create_packet();
	if( NULL == p )
		return NULL;

	if( this->header_ )
	{
		p->header_ = this->header_->clone( this->header_->flags() );
		if( NULL == p->header_ )
		{
			delete p;
			return NULL;
		}
	}

	if( this->body_ )
	{
		p->body_ = this->body_->clone( this->body_->flags() );
		if( NULL == p->body_ )
		{
			delete p;
			return NULL;
		}
	}
	p->token_ = this->token_;
	return p;
}

bool
packet_impl::build_heartbeat_pkt()
{
	if( NULL == this->header_ )
	{
		if( !create_header() )
			return false;
	}

	build_header(0, 0, aot::inet::e_pkt_type_heartbeat);

	if( this->body_ )
	{
		this->body_->release();
		this->body_ = NULL;
	}
	return true;
}

packet_impl* 
packet_impl::create_packet()
{
	packet_impl* r = NULL;
	ACE_NEW_NORETURN(r, packet_impl);
	if( NULL == r)
	{
		aot_log_error(AOT_LM_ERROR, "no memory! packet_impl::create_packet()");
	}
	return r;
}